1. Назначение
MotorStep V8 — прошивка для управления поворотным столом на шаговом моторе через драйвер TB6600. Предназначена для производственных задач, где требуется:
- Точное позиционирование стола в диапазоне 0…360°
- Плавное движение (трапециевидный профиль скорости) для тяжёлых столов (50–1500 кг)
- Автоматический поиск нуля (концевик) при старте
- Ручное управление через энкодер HW-040 и кнопки
- Внешнее управление через Serial (Console) и Wi-Fi (Web UI)
- Обратная связь по углу с оптического энкодера MBL3806
MotorStep_v8.ino. Классы не знают друг о друге — только через main.
2. Возможности V8
🌐 Wi-Fi AP
ESP32 создаёт сеть MotorStep_V8 / newpribor. Управление с телефона/ПК.
🖥️ Web UI
Полноценный интерфейс: управление, индикация, настройки плавности, лог событий.
📡 WebSocket
Живая передача данных через JSON-статус раз в секунду. Реальное время.
🎯 Точность
0.1° по MBL3806 (24000 импульсов на оборот стола при GEAR_RATIO=10).
⚡ Плавность
Трапециевидный профиль: разгон, плато, торможение. Настройка через Web/Console.
🏠 Автопоиск нуля
4 этапа + пауза 1 сек. Защита по углу (405°). Концевик обязателен.
🛑 Мгновенный stop
Остановка за один шаг (≤800 мкс). Без инерции, без «догонов».
📟 Дисплей TM1637
3 значения: цель, угол стола, MBL3806. Режимы d1/d2. Индикация Run, EROR, BLOC/OFF.
💾 NVS-память
Сохранение шага, флага findHome, accel/cruise/start в энергонезависимую память.
🔄 Двойной протокол
Один обработчик команд для Serial и WebSocket. Управление с обоих каналов одновременно.
🎛️ Инверсия MBL
Переключение направления через #define POSITION_INVERTED — без перепайки.
🔌 Модульность
Замена любого класса (например, Display на LCD) не требует изменений в других.
3. Подключение элементов
3.1. Карта пинов
| GPIO | Функция | Что подключено | Примечание |
|---|---|---|---|
0 | EncoderHW040 CLK | HW-040 CLK | ISR, CHANGE |
1 | EncoderHW040 DT | HW-040 DT | ISR, CHANGE |
2 | Кнопка дисплея | Кнопка (на GND) | Strapping — свой опрос |
3 | EncoderHW040 SW | HW-040 SW | GyverButton |
4 | TM1637 CLK | Дисплей TM1637 | — |
5 | TM1637 DIO | Дисплей TM1637 | — |
6 | TB6600 STEP | TB6600 PUL+ | Импульсы шага |
7 | TB6600 DIR | TB6600 DIR+ | Направление |
8 | Концевик HOME | Механический/индуктивный | INPUT_PULLUP, LOW = сработал |
9 | Резерв | — | Свободен |
10 | TB6600 ENA | TB6600 ENA+ | LOW = мотор включён |
20 | MBL3806 A | MBL3806 A | UART0 RX — 1 кОм, INPUT_PULLUP |
21 | MBL3806 B | MBL3806 B | UART0 TX — 1 кОм, INPUT_PULLUP |
3.2. Схема соединений
TB6600 (драйвер шагового мотора)
ESP32-C3 TB6600
─────────────────────────────
GPIO 6 ──── 1кОм ──── PUL+ (STEP)
GPIO 7 ──── 1кОм ──── DIR+
GPIO 10 ──── 1кОм ──── ENA+
GND ────────────── PUL- / DIR- / ENA- (общий)
MBL3806 (оптический энкодер на моторе)
ESP32-C3 MBL3806
─────────────────────────────
+5V ────────────── VCC (красный)
GND ────────────── GND (чёрный)
GPIO 20 ──── 1кОм ──── A (зелёный)
GPIO 21 ──── 1кОм ──── B (белый)
HW-040 (энкодер ручного управления)
ESP32-C3 HW-040
─────────────────────────────
+3.3V ────────────── VCC
GND ────────────── GND
GPIO 0 ────────────── CLK
GPIO 1 ────────────── DT
GPIO 3 ────────────── SW (кнопка)
TM1637 (дисплей)
ESP32-C3 TM1637
─────────────────────────────
+5V ────────────── VCC
GND ────────────── GND
GPIO 4 ────────────── CLK
GPIO 5 ────────────── DIO
Кнопка дисплея
ESP32-C3
─────────────────────────────
GPIO 2 ──[Кнопка]── GND
Концевик HOME
ESP32-C3
─────────────────────────────
GPIO 8 ──[Концевик NO]── GND
При срабатывании замыкается на GND → LOW. В покое — HIGH (INPUT_PULLUP).
3.3. Питание
| Потребитель | Напряжение | Ток | Источник |
|---|---|---|---|
| ESP32-C3 Mini | 5 В (USB) | ~250 мА | USB или БП |
| TB6600 (логика) | 5 В | ~20 мА | БП 5 В |
| TB6600 (мотор) | 24–48 В | до 3 А | Отдельный БП |
| MBL3806 | 5 В | ~50 мА | БП 5 В |
| TM1637 | 5 В | ~30 мА | БП 5 В |
| HW-040 | 3.3 В | ~5 мА | ESP32 |
4. Настройки
4.1. Пины и механика (в коде)
Пины — в соответствующих .cpp файлах классов
| Класс | Файл | Что настраивается |
|---|---|---|
| Display | Display.cpp | PIN_CLK_DISP=4, PIN_DIO_DISP=5 |
| Buttons | Buttons.cpp | PIN_ENC_SW=3, PIN_DISP_BTN=2, PIN_HOME=8 |
| EncoderHW040 | EncoderHW040.cpp | PIN_ENC_CLK=0, PIN_ENC_DT=1 |
| Position | Position.cpp | PIN_MBL_A=20, PIN_MBL_B=21 |
| Motor | Motor.cpp | PIN_STEP=6, PIN_DIR=7, PIN_ENA=10 |
| WebUI | WebUI.cpp | HTTP 80, WebSocket 81 |
Motor.cpp — в начале файла
static const int32_t STEPS_PER_REV = 800; // шагов мотора на оборот (1/4 микрошаг)
static const float GEAR_RATIO = 10.0; // ← РЕДУКТОР (мотор:стол = 10:1)
static const int32_t ANGLE_MIN = 0;
static const int32_t ANGLE_MAX = 360;
Position.cpp — инверсия MBL
#define POSITION_INVERTED 0 // 0 = прямой, 1 = инверсный (A/B поменяны)
main — Wi-Fi AP
#define WIFI_SSID "MotorStep_V8"
#define WIFI_PASS "newpribor"
4.2. NVS (энергонезависимая память)
Сохраняются в NVS (namespace "motorstep"):
| Ключ | Тип | Дефолт | Что значит |
|---|---|---|---|
step | int | 5 | Текущий шаг (1..360°) |
findHome | bool | true | Искать ноль при старте |
accel | int | 1000 | Шагов на разгон/торможение |
cruise | int | 800 | Задержка на плато (мкс) — макс. скорость |
start | int | 5000 | Задержка на старте/стопе (мкс) |
Управление — командами accel, cruise, start (с сохранением в NVS).
5. Console (Serial)
Скорость: 115200. Line Ending: Newline или Both NL & CR.
5.1. Команды
| Команда | Что делает | Ответ |
|---|---|---|
move <angle> | Перейти к углу (0..360) | OK / BUSY |
home | Поиск нуля | OK |
reset | Сброс позиции в 0 | OK |
hold | Удержание/освобождение мотора | OK |
stop | Мгновенный стоп (без сбросов) | OK |
stop! | Стоп с ошибкой (мотор освобождён) | OK |
clear | Сброс ошибки | OK |
next | Следующий шаг (180→90→10→5→1→180) | OK |
setstep <n> | Установить шаг 1..360 (сохр. в NVS) | OK |
accel <n> | Установить accel (сохр. в NVS) | OK |
cruise <n> | Установить cruise (сохр. в NVS) | OK |
start <n> | Установить start (сохр. в NVS) | OK |
save | Сохранить в NVS | OK |
load | Загрузить из NVS | OK |
hb <0|1> | Heartbeat вкл/выкл | OK |
help | Список команд | OK + help |
5.2. Запросы
| Команда | Ответ |
|---|---|
ready? | READY / BUSY |
status? | IDLE / MOVING |
angle? | Целевой угол |
motor? | Угол стола (факт) |
mbl? | Угол MBL3806 |
step? | Текущий шаг (1..360) |
error? | OK / ERROR |
hold? | ON / OFF |
hb? | ON / OFF |
accel? / cruise? / start? | Значение параметра |
Асинхронные события (ESP → ПК)
| Событие | Когда |
|---|---|
DONE | Мотор завершил движение |
READY | Контроллер свободен |
HB | Heartbeat (если включён) |
6. Web UI (Wi-Fi)
6.1. Подключение
- Прошейте плату
- На телефоне/ПК подключитесь к Wi-Fi: SSID
MotorStep_V8, парольnewpribor - Откройте браузер →
http://192.168.4.1/ - Индикатор ONLINE (зелёный) — соединение установлено
6.2. Блоки интерфейса
📊 Индикатор
| Поле | Что показывает |
|---|---|
| Задано (крупно) | Целевой угол _targetAngle |
| Факт (энкодер) (крупно) | Угол MBL3806 position.getAngle() |
| Статус | ГОТОВ / ДВИЖЕНИЕ |
| Ошибка | НЕТ / ОШИБКА |
| Удержание | ДА / НЕТ |
| Шаг | Текущий шаг (1..360°) |
📏 Шаг
- ◀ НАЗАД — движение на шаг назад
- NEXT STEP — переключение шага по циклу 180→90→10→5→1→180
- ВПЕРЁД ▶ — движение на шаг вперёд
- В заголовке отображается текущий шаг
🎛️ Управление
- Поле угла + ПЕРЕЙТИ — переход к заданному углу
- 🏠 — HOME (поиск нуля)
- STOP — мгновенная остановка
- СБРОС — сброс позиции в 0
- HOLD — удержание/освобождение мотора
- STOP! — стоп с ошибкой (мотор освобождён)
- CLEAR — сброс ошибки
⚡ Плавность
- accel + ПРИМЕНИТЬ — шагов на разгон/торможение
- cruise + ПРИМЕНИТЬ — задержка на плато (мкс)
- start + ПРИМЕНИТЬ — задержка на старте/стопе (мкс)
📜 Лог событий
- Показывает последние 50 сообщений от ESP
- Синий — отправленные команды (>>)
- Зелёный — ответы (OK, DONE, READY)
- Красный — ошибки
8. Дисплей TM1637
Режимы (переключаются кнопкой GPIO 2)
| Режим | Индикатор | Формат | Что показывает |
|---|---|---|---|
| d1 | d 1 | XXX | Угол стола (факт мотора) |
| d2 | d 2 | _XXX | Угол MBL3806 (с подчёркиванием) |
Приоритет отображения
- EROR — мигает при ошибке
- Run — во время движения мотора
- S XX — 1 сек после смены шага
- BLOC / OFF — 1 сек после переключения удержания
- d1 / d2 — 1 сек после переключения режима
- Цель — 1 сек после вращения энкодера
- Угол — основное (d1: мотор, d2: MBL)
Специальные сообщения
| Текст | Что значит |
|---|---|
Run | Мотор движется (R большая, u n маленькие) |
EROR | Ошибка (мигает) |
S 90 | Выбран шаг 90° |
BLOC | Мотор удерживается |
OFF | Мотор освобождён |
d 1 / d 2 | Режим дисплея |
9. Компиляция
9.1. Плата
| Параметр | Значение |
|---|---|
| Board | ESP32C3 Dev Module |
| Чип | ESP32-C3 |
| Плата | ESP32-C3 Mini V1 (или аналог) |
9.2. Библиотеки
Установить через Library Manager (Sketch → Include Library → Manage Libraries):
| Библиотека | Автор | Для чего |
|---|---|---|
| TM1637Display | Avishay Orpaz | Дисплей |
| GyverButton | AlexGyver | Кнопка энкодера (SW) |
| WebSockets | Markus Sattler (Links2004) | WebSocket-сервер |
WebSockets (не arduinoWebSockets-master). Arduino IDE ищет по имени папки.
WiFi.h, WebServer.h — входят в пакет ESP32.
9.3. Настройки Arduino IDE (Tools)
| Настройка | Значение | Почему |
|---|---|---|
| Board | ESP32C3 Dev Module | Правильный чип |
| USB CDC On Boot | Enabled | Serial через USB (Console работает) |
| CPU Frequency | 160 MHz | Скорость |
| Flash Size | 4MB (32Mb) | Стандарт |
| Upload Speed | 921600 | Быстрая прошивка |
| JTAG Adapter | Disabled | Не занимает GPIO 0-5 |
| USB DFU On Boot | Disabled | Не нужно |
9.4. Прошивка
- Подключить ESP32-C3 через USB
- Выбрать порт в Tools → Port
- Нажать Upload (Ctrl+U)
- Если не прошивается: зажать BOOT, нажать RESET, отпустить RESET, отпустить BOOT, затем Upload
- После прошивки — нажать RESET
10. Известные проблемы и особенности
Плавность vs Wi-Fi
Wi-Fi-стек и WebSocket занимают время CPU при каждом вызове. Решение: webui.update() вызывается раз в 20 мс (не каждый loop). Без этого мотор пропускает шаги.
// В loop() main
static uint32_t lastWebUiUpdate = 0;
if (millis() - lastWebUiUpdate > 20) {
lastWebUiUpdate = millis();
webui.update();
}
Пропуски энкодера HW-040
Механический энкодер даёт дребезг. Решение: антидребезг 2000 мкс в ISR + REPORT_MIN_INTERVAL_MS = 50 мс. Редкие пропуски возможны.
Двойное срабатывание кнопки GPIO 2
Strapping-пин, дешёвая кнопка. Решение: state machine в Buttons.cpp, антидребезг 50 мс.
Конфликт GPIO 20/21 (UART0)
GPIO 20/21 — UART0 (RX/TX). Serial для Console использует USB CDC (виртуальный COM-порт), не занимает эти пины. Поэтому MBL3806 работает без конфликтов.
Кнопка HW-040 SW на GPIO 3
Strapping-пин (JTAG source). С JTAG Adapter = Disabled работает нормально.
11. Проверено и однозначно не работает
| Что | Результат | Причина |
|---|---|---|
| GyverButton на GPIO 2 | НЕ работает | GPIO 2 — strapping. Заменено на state machine. |
| GyverEncoder на ESP32-C3 | НЕ работает | Библиотека под AVR/ESP8266. Заменено на собственный ISR-декодер. |
| Точка на TM1637 | НЕ работает | Библиотека не выводит точку корректно. Заменено на _ перед числом для MBL. |
| PROGRESS каждые 1° | НЕ работает плавно | Serial блокирует loop → рывки. Отключено. |
| webui.update() каждый loop | НЕ работает плавно | Wi-Fi стек ест время. Вызывать раз в 20 мс. |
| GPIO 0, 1 при загрузке | Осторожно | HW-040 CLK/DT. Если крутить при загрузке — может помешать. |
| GPIO 8 при загрузке | Осторожно | Концевик HOME. Должен быть HIGH (разомкнут) при загрузке. |
| GPIO 9 при загрузке | ОК | Strapping (BOOT). Не используется. |
12. Состав проекта
MotorStep_v8/
├── MotorStep_v8.ino ← main (дирижёр)
├── Display.h / Display.cpp ← TM1637
├── Buttons.h / Buttons.cpp ← HW-040 SW + GPIO 2 + концевик
├── EncoderHW040.h / EncoderHW040.cpp ← HW-040 (ISR-декодер)
├── Settings.h / Settings.cpp ← NVS
├── Position.h / Position.cpp ← MBL3806
├── Motor.h / Motor.cpp ← шаговый мотор
├── Console.h / Console.cpp ← Serial-протокол
└── WebUI.h / WebUI.cpp ← Wi-Fi AP + HTTP + WebSocket
Зависимости
Классы не знают друг о друге. Все связи — через main:
main → motor.moveTo(angle)
main → display.setMotorAngle()
main → settings.getStep()
main → position.getAngle()
main → console.sendDone()
main → webui.sendFullStatus()
13. История версий
| Версия | Что нового |
|---|---|
| V6 |
• Классовая архитектура (7 классов) • Console (Serial-протокол) • NVS (Settings) • GEAR_RATIO • Индикация d1/d2, Run, EROR • findHome с 4 этапами |
| V8 |
• WebUI (Wi-Fi AP + HTTP + WebSocket) • JSON-статус раз в 1 сек • Web-интерфейс с управлением и индикацией • Поля плавности в Web (авто-обновление) • webui.update() раз в 20 мс (ключ к плавности)• Шаг как число (1..360), команда setstep• findHome — пауза 1 сек после отхода• stop — без сбросов, возврат к старому нулю• STOP! при концевике вне 0/360 • Новый дизайн Web UI |